package com.hui.qiniucloud.controller;

import com.hui.qiniucloud.entity.AICharacter;
import com.hui.qiniucloud.entity.Result;
import com.hui.qiniucloud.service.*;
import com.hui.qiniucloud.service.impl.MockAsrService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/api/voice-chat")
@CrossOrigin(origins = "*")
@RequiredArgsConstructor
@Tag(name = "AI角色语音聊天", description = "提供AI角色扮演的语音和文字聊天功能")
public class VoiceChatController {

    @Autowired
    private IAsrService asrService;

    @Autowired
    private MockAsrService mockAsrService;

    @Autowired
    private IDoubaoService doubaoService;

    @Autowired
    private ITtsService ttsService;

//    private final ImageService imageService ;

    @Autowired
    private ICharacterService characterService;

    @Operation(summary = "上传图片")
    @PostMapping("/uploadImage")
    public Result uploadImage(@RequestParam("file") MultipartFile mpFile) throws IOException {
        return characterService.uploadImage(mpFile);
    }
    /**
     * 实时语音聊天 - 完整流程
     */
    @Operation(summary = "语音聊天流式接口",
               description = "上传语音文件，进行语音识别后与指定角色进行AI对话，返回流式响应")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功处理语音聊天请求",
                    content = @Content(mediaType = "text/event-stream")),
        @ApiResponse(responseCode = "400", description = "请求参数错误"),
        @ApiResponse(responseCode = "404", description = "角色不存在"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping(value = "/stream/{characterId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> voiceChatStream(
            @Parameter(description = "角色ID", example = "harry_potter")
            @PathVariable @NotBlank String characterId,
            @Parameter(description = "语音文件 (支持 WAV, MP3, WebM 格式)", required = true)
            @RequestParam("audio") @NotNull MultipartFile audioFile) {

        return Mono.fromCallable(() -> {
                    try {
                        return audioFile.getBytes();
                    } catch (Exception e) {
                        throw new RuntimeException("音频文件读取失败", e);
                    }
                })
                .flatMap(asrService::recognizeAudio) // 语音识别
                .flatMapMany(text -> {
                    if (text == null || text.trim().isEmpty()) {
                        return Flux.just("data: {\"error\": \"语音识别失败\"}\n\n");
                    }

                    AICharacter character = characterService.getCharacterById(characterId);
                    if (character == null) {
                        return Flux.just("data: {\"error\": \"角色不存在\"}\n\n");
                    }

                    // 发送识别到的文本
                    Flux<String> asrResult = Flux.just("data: {\"type\": \"asr\", \"text\": \"" + text + "\"}\n\n");

                    // 获取AI回复
                    Flux<String> aiResponse = doubaoService.chatStreamWithCharacter(text, character, null)
                            .map(content -> "data: {\"type\": \"ai_text\", \"content\": \"" + content.replace("\"", "\\\"") + "\"}\n\n");

                    return Flux.concat(asrResult, aiResponse);
                })
                .onErrorReturn("data: {\"error\": \"处理失败\"}\n\n");
    }

    /**
     * 文本转语音
     */
    @Operation(summary = "文本转语音",
               description = "将文本转换为指定角色的语音，返回音频文件")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功生成语音文件",
                    content = @Content(mediaType = "audio/mpeg")),
        @ApiResponse(responseCode = "400", description = "请求参数错误"),
        @ApiResponse(responseCode = "404", description = "角色不存在"),
        @ApiResponse(responseCode = "500", description = "语音合成失败")
    })
    @PostMapping("/tts/{characterId}")
    public Mono<ResponseEntity<byte[]>> textToSpeech(
            @Parameter(description = "角色ID", example = "hermione")
            @PathVariable @NotBlank String characterId,
            @Parameter(description = "文本转语音请求", required = true)
            @RequestBody @Valid Map<String, String> request) {

        String text = request.get("text");
        if (text == null || text.trim().isEmpty()) {
            return Mono.just(ResponseEntity.badRequest().build());
        }

        AICharacter character = characterService.getCharacterById(characterId);
        String voiceType = character != null ? character.getVoiceType() : "zh_female_wanqudashu_moon_bigtts";
        HttpHeaders headers = new HttpHeaders();
        // 🌟 关键：告诉浏览器这是 MP3 音频
        headers.setContentType(MediaType.parseMediaType("audio/mpeg"));
        // 🌟 关键：设置下载的文件名，后缀必须是 .mp3
        headers.setContentDispositionFormData("attachment", "response.mp3");

        Mono<ResponseEntity<byte[]>> responseEntityMono = ttsService.synthesizeSpeech(text, voiceType)
                .map(audioData -> ResponseEntity.ok()
                        .contentType(MediaType.parseMediaType("audio/mpeg"))
                        .headers(headers)
                        .body(audioData))
                .onErrorReturn(ResponseEntity.internalServerError().build());
        return responseEntityMono;
    }

    /**
     * 纯文本聊天（支持SSE流式响应）
     */
    @Operation(summary = "文本聊天流式接口",
               description = "与指定角色进行文字对话，支持聊天历史，返回流式响应")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功处理文本聊天请求",
                    content = @Content(mediaType = "text/event-stream")),
        @ApiResponse(responseCode = "400", description = "消息内容不能为空"),
        @ApiResponse(responseCode = "404", description = "角色不存在"),
        @ApiResponse(responseCode = "500", description = "AI服务异常")
    })
    @PostMapping(value = "/text-stream/{characterId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> textChatStream(
            @Parameter(description = "角色ID", example = "socrates")
            @PathVariable @NotBlank String characterId,
            @Parameter(description = "聊天请求，包含消息和历史记录")
            @RequestBody @Valid Map<String, Object> request) {

        String message = (String) request.get("message");
        List<Map<String, String>> chatHistory = (List<Map<String, String>>) request.get("chatHistory");

        if (message == null || message.trim().isEmpty()) {
            return Flux.just("data: {\"error\": \"消息不能为空\"}\n\n");
        }

        AICharacter character = characterService.getCharacterById(characterId);
        if (character == null) {
            return Flux.just("data: {\"error\": \"角色不存在\"}\n\n");
        }

        return doubaoService.chatStreamWithCharacter(message, character, chatHistory)
                .map(content -> "data: {\"type\": \"ai_text\", \"content\": \"" + content.replace("\"", "\\\"") + "\"}\n\n")
                .onErrorReturn("data: {\"error\": \"AI服务异常\"}\n\n");
    }

    /**
     * 获取支持的角色列表
     */
    @Operation(summary = "获取角色列表",
               description = "获取系统中所有可用的AI角色列表")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功获取角色列表",
                    content = @Content(mediaType = "application/json",
                                     schema = @Schema(implementation = AICharacter[].class))),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/characters")
    public ResponseEntity<List<AICharacter>> getCharacters() {
        List<AICharacter> characters = characterService.getAllCharacters();
        return ResponseEntity.ok(characters);
    }

    /**
     * 获取特定角色信息
     */
    @Operation(summary = "获取角色详情",
               description = "根据角色ID获取详细的角色信息")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功获取角色信息",
                    content = @Content(mediaType = "application/json",
                                     schema = @Schema(implementation = AICharacter.class))),
        @ApiResponse(responseCode = "404", description = "角色不存在"),
        @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/characters/{characterId}")
    public ResponseEntity<AICharacter> getCharacter(
            @Parameter(description = "角色ID", example = "einstein")
            @PathVariable @NotBlank String characterId) {
        AICharacter character = characterService.getCharacterById(characterId);
        if (character == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(character);
    }
}